package imp

import (
	sqlc "bgs/db/sqlc"
	wxpayApplymentGrpc "bgs/grpc/gen/service/wxpay_applyment"
	"bgs/grpc/gen/shared/message"
	"bgs/grpc/imp/enums"
	brandService "bgs/service/brand"
	"bgs/util"
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
)

/****************************************************************************************/
/*                               wxpay_applyment entity of helper                       */
/****************************************************************************************/

func transformWxpayApplymentEntityToPb(o sqlc.WxpayApplyment) *wxpayApplymentGrpc.WxpayApplymentEntity {
	return &wxpayApplymentGrpc.WxpayApplymentEntity{
		Id:                  o.ID,
		BrandId:             o.BrandID,
		WxpayMchIdAsService: o.WxpayMchIDAsService,
		ProxyApplyStatus:    o.ProxyApplyStatus,
		ApplyFormData:       string(o.ApplyFormData),
		ApplyNo:             o.ApplyNo.String,
		WxApplymentId:       o.WxApplymentID.String,
		ApplyState:          o.ApplyState.String,
		ApplyStateDesc:      o.ApplyStateDesc.String,
		SignUrl:             o.SignUrl.String,
		AccountValidation:   string(o.AccountValidation.RawMessage),
		WxpayMchIdAsSub:     o.WxpayMchIDAsSub.String,
		AuditDetails:        string(o.AuditDetails.RawMessage),
		LegalValidationUrl:  o.LegalValidationUrl.String,
	}
}

/****************************************************************************************/
/*                               wxpay_applyment entity of cmd                          */
/****************************************************************************************/

// UpsertWxpayApplyment 创建品牌微信支付申请
func (s *BrandAPIService) UpsertWxpayApplyment(ctx context.Context, req *wxpayApplymentGrpc.UpsertWxpayApplymentRequest) (res *wxpayApplymentGrpc.UpsertWxpayApplymentResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("wxpay_applymentImp->UpsertWxpayApplyment:%v", req)
	res = &wxpayApplymentGrpc.UpsertWxpayApplymentResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brandID := req.BrandId
	arg := sqlc.UpsertWxpayApplymentParams{
		BrandID:             req.BrandId,
		WxpayMchIDAsService: req.WxpayMchIdAsService,
		ApplyFormData:       json.RawMessage(req.ApplyFormData),
	}
	wxpayApplyment, err := s.dao.Q.UpsertWxpayApplyment(ctx, arg)

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	slog.Infof("UpsertWxpayApplyment db process success: %v", wxpayApplyment.BrandID)
	res.WxpayApplyment = transformWxpayApplymentEntityToPb(wxpayApplyment)
	slog.Infof("UpsertWxpayApplyment prepare FetchBrand: %v", wxpayApplyment.BrandID)
	cBrand := s.cacher.FetchBrand(brandID)
	
	if cBrand == nil {
		err = fmt.Errorf("not found brand of brandID:%d", brandID)
		return
	}

	slog.Infof("UpsertWxpayApplyment FetchBrand success: %v", cBrand)
	res.SgId = cBrand.SgID
	return
}

// UpdateWxpayApplymentApplyNo 更新品牌微信支付申请的代理申请号
func (s *BrandAPIService) UpdateWxpayApplymentApplyNo(ctx context.Context, req *wxpayApplymentGrpc.UpdateWxpayApplymentApplyNoRequest) (res *wxpayApplymentGrpc.UpdateWxpayApplymentApplyNoResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("wxpay_applymentImp->UpdateWxpayApplymentApplyNo:%v", req)
	res = &wxpayApplymentGrpc.UpdateWxpayApplymentApplyNoResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpdateWxpayApplymentApplyNoParams{
		ID:      req.Id,
		ApplyNo: sqlc.NSFromString(req.ApplyNo),
	}
	WxpayApplyment, err := s.dao.Q.UpdateWxpayApplymentApplyNo(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.WxpayApplyment = transformWxpayApplymentEntityToPb(WxpayApplyment)
	return
}

// UpdateWxpayApplymentProxyResult 更新品牌微信支付申请的代理结果
func (s *BrandAPIService) UpdateWxpayApplymentProxyResult(ctx context.Context, req *wxpayApplymentGrpc.UpdateWxpayApplymentProxyResultRequest) (res *wxpayApplymentGrpc.UpdateWxpayApplymentProxyResultResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("wxpay_applymentImp->UpdateWxpayApplymentApplyNo:%v", req)
	res = &wxpayApplymentGrpc.UpdateWxpayApplymentProxyResultResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpdateWxpayApplymentProxyResultParams{
		ID:                 req.Id,
		WxApplymentID:      sqlc.NSFromString(req.WxApplymentId),
		ApplyState:         sqlc.NSFromString(req.ApplyState),
		ApplyStateDesc:     sqlc.NSFromString(req.ApplyStateDesc),
		SignUrl:            sqlc.NSFromString(req.SignUrl),
		AccountValidation:  sqlc.NRawMessageFromRawMessage(json.RawMessage(req.AccountValidation)),
		WxpayMchIDAsSub:    sqlc.NSFromString(req.WxpayMchIdAsSub),
		AuditDetails:       sqlc.NRawMessageFromRawMessage(json.RawMessage(req.AuditDetails)),
		LegalValidationUrl: sqlc.NSFromString(req.LegalValidationUrl),
		ApplyFormData:      json.RawMessage(req.ApplyFormData),
	}
	WxpayApplyment, err := s.dao.Q.UpdateWxpayApplymentProxyResult(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.WxpayApplyment = transformWxpayApplymentEntityToPb(WxpayApplyment)
	return
}

/****************************************************************************************/
/*                               wxpay_applyment entity of query                        */
/****************************************************************************************/

// GetWxpayApplyment 获取单个品牌的微信支付申请
func (s *BrandAPIService) GetWxpayApplyment(ctx context.Context, req *wxpayApplymentGrpc.GetWxpayApplymentRequest) (res *wxpayApplymentGrpc.GetWxpayApplymentResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("wxpay_applymentImp->GetWxpayApplyment:%v", req)
	res = &wxpayApplymentGrpc.GetWxpayApplymentResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	WxpayApplyment, err := s.dao.Q.GetWxpayApplyment(ctx, req.Id)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.WxpayApplyment = transformWxpayApplymentEntityToPb(WxpayApplyment)
	return
}

// GetWxpayApplymentByBrandID 品牌获取单个品牌的微信支付申请
func (s *BrandAPIService) GetWxpayApplymentByBrandID(ctx context.Context, req *wxpayApplymentGrpc.GetWxpayApplymentByBrandIDRequest) (res *wxpayApplymentGrpc.GetWxpayApplymentByBrandIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("wxpay_applymentImp->GetWxpayApplymentByBrandID:%v", req)
	res = &wxpayApplymentGrpc.GetWxpayApplymentByBrandIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	WxpayApplyment, sqlErr := s.dao.Q.GetWxpayApplymentByBrandID(ctx, req.BrandId)
	if sqlErr != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    util.Int32IfThenElse(sql.ErrNoRows == sqlErr, 404, 400),
			Msg:     sqlErr.Error(),
		}
		return
	}
	res.WxpayApplyment = transformWxpayApplymentEntityToPb(WxpayApplyment)
	return
}

// GetWxpayApplymentAndRemindWxpay 品牌获取单个品牌的微信支付申请并强制提醒wxpay刷新
func (s *BrandAPIService) GetWxpayApplymentAndRemindWxpay(ctx context.Context, req *wxpayApplymentGrpc.GetWxpayApplymentAndRemindWxpayRequest) (res *wxpayApplymentGrpc.GetWxpayApplymentAndRemindWxpayResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("wxpay_applymentImp->GetWxpayApplymentAndRemindWxpay:%v", req)
	res = &wxpayApplymentGrpc.GetWxpayApplymentAndRemindWxpayResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q

	wxpayApplyment, sqlErr := q.GetWxpayApplymentByBrandID(ctx, req.BrandId)
	if sqlErr != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    util.Int32IfThenElse(sql.ErrNoRows == sqlErr, 404, 400),
			Msg:     sqlErr.Error(),
		}
		return
	}

	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {

		synced, err := s.brandService.SyncWxpayApplyment(ctx, q, brandService.SyncWxpayApplymentParam{
			WxpayApplymentPtr: &wxpayApplyment,
		})
		if err != nil {
			return
		}
		slog.Infof("更新微信支付商户进件代理信息-from用户主动 ok")
		applyState := synced.ApplyState.String
		subMchID := synced.WxpayMchIDAsSub.String
		if applyState == string(enums.ApplymentStateFinish) {
			// 内部有清空缓存,尽量把该方法放到事务最后
			err = s.brandService.FinishWxpayApplyment(ctx, q, brandService.FinishWxpayApplymentParam{
				WxpayApplymentPtr: &wxpayApplyment,
				SubMchID:          subMchID,
			})
			if err != nil {
				return
			}
			slog.Infof("商户进件完成,更新品牌扩展信息-from用户主动 ok")
		}
		wxpayApplyment = *synced
		return
	})
	if err != nil {
		return
	}

	res.WxpayApplyment = transformWxpayApplymentEntityToPb(wxpayApplyment)
	return
}
